
#include <BOpenGL>
#include <BPainter>
#include <BMouseEvent>
#include <BChangeEvent>
#include <BScrollBar>
#include <BKeyEvent>

#include <BTableWidget>
#include "member_BTableWidget.h"
#include "member_BTableItem.h"

using namespace BWE;

#define member					(*(member_BTableWidget*)_ptr)
#define member_allocate()		_ptr = new member_BTableWidget(this)
#define member_release()		delete (member_BTableWidget*)_ptr

BTableWidget::BTableWidget(BWidget* parent) : BScrollArea(parent)
{
	member_allocate();
}
BTableWidget::~BTableWidget()
{
	member_release();
}

bool BTableWidget::setRowCount(int rowCount)
{
	if (!member.items.setRow(rowCount))
		return false;
	member.rowHeader.sections.resize(member.items.row());
	member.selectedItems.clear();
	member.hoverItem = 0;
	member.shiftItem = 0;
	member.rowHeader.dirty = true;
	member.dirty = true;
	this->fresh();
	return true;
}
int BTableWidget::rowCount() const
{
	return member.rowHeader.sections.size();
}

bool BTableWidget::setRowLabel(int row, const BString& text)
{
	if (member.rowHeader.sections.check(row))
	{
		HeaderSection& sec = member.rowHeader.sections[row];
		if (sec.text != text)
		{
			sec.text = text;
			sec.dirty = true;
			member.rowHeader.dirty = true;
			this->fresh();
		}
		return true;
	}
	return false;
}
const BString& BTableWidget::rowLabel(int row) const
{
	return member.rowHeader.sections(row).text;
}

void BTableWidget::setRowVisible(int row, bool visible)
{
	if (member.rowHeader.sections.check(row))
	{
		HeaderSection& sec = member.rowHeader.sections[row];
		if (sec.visible != visible)
		{
			sec.visible = visible;
			sec.dirty = true;
			member.rowHeader.dirty = true;
			member.dirty = true;
			this->fresh();
		}
	}
}
bool BTableWidget::rowVisible(int row) const
{
	return member.rowHeader.sections(row).visible;
}

bool BTableWidget::setColumnCount(int columnCount)
{
	if (!member.items.setColumn(columnCount))
		return false;
	member.columnHeader.sections.resize(columnCount);
	member.columnHeader.dirty = true;
	member.dirty = true;
	this->fresh();
	return true;
}
int BTableWidget::columnCount() const
{
	return member.columnHeader.sections.size();
}

bool BTableWidget::setColumnLabel(int column, const BString& text)
{
	if (member.columnHeader.sections.check(column))
	{
		HeaderSection& sec = member.columnHeader.sections[column];
		if (sec.text != text)
		{
			sec.text = text;
			sec.dirty = true;
			member.columnHeader.dirty = true;
			member.dirty = true;
			this->fresh();
		}
		return true;
	}
	return false;
}
const BString& BTableWidget::columnLabel(int column) const
{
	return member.columnHeader.sections(column).text;
}

void BTableWidget::setColumnVisible(int column, bool visible)
{
	if (member.columnHeader.sections.check(column))
	{
		HeaderSection& sec = member.columnHeader.sections[column];
		if (sec.visible != visible)
		{
			sec.visible = visible;
			sec.dirty = true;
			member.dirty = true;
			this->fresh();
		}
	}
}
bool BTableWidget::columnVisible(int column) const
{
	return member.columnHeader.sections(column).visible;
}

bool BTableWidget::appendRow(int count)
{
	if (member.items.appendRow(count))
	{
		member.rowHeader.sections.append(HeaderSection(), count);
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
bool BTableWidget::insertRow(int pos, int count)
{
	if (member.items.insertRow(pos, count))
	{
		member.rowHeader.sections.insert(pos, HeaderSection(), count);
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
bool BTableWidget::removeRow(int pos, int count)
{
	if (pos < 0 && pos >= member.items.row())
		return false;
	if (count < 1)
		return 0;
	for (int i = 0; i < member.selectedItems.size(); i++)
	{
		BTableItem* item = member.selectedItems[i];
		if (item->row() >= pos && item->row() < pos + count)
			member.selectedItems[i] = 0;
	}
	member.selectedItems.remove(0);
	member.hoverItem = 0;
	member.shiftItem = 0;

	if (member.items.removeRow(pos, count))
	{
		member.rowHeader.sections.remove(pos, count);
		member.selectedItems.clear();
		member.rowHeader.dirty = true;
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}

bool BTableWidget::appendColumn(int count)
{
	if (member.items.appendColumn(count))
	{
		member.columnHeader.sections.append(HeaderSection(), count);
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
bool BTableWidget::insertColumn(int pos, int count)
{
	if (member.items.insertColumn(pos, count))
	{
		member.columnHeader.sections.insert(pos, HeaderSection(), count);
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}
bool BTableWidget::removeColumn(int pos, int count)
{
	if (pos < 0 && pos >= member.items.column())
		return false;
	return false;
	if (count < 1)
		return 0;
	for (int i = 0; i < member.selectedItems.size(); i++)
	{
		BTableItem* item = member.selectedItems[i];
		if (item->column() >= pos && item->column() < pos + count)
			member.selectedItems[i] = 0;
	}

	member.selectedItems.remove(0);
	member.hoverItem = 0;
	member.shiftItem = 0;
	if (member.items.removeColumn(pos, count))
	{
		member.columnHeader.sections.remove(pos, count);
		member.columnHeader.dirty = true;
		if (member.items.empty())
		{
			member.rowHeader.sections.clear();
			member.rowHeader.dirty = true;
		}
		member.dirty = true;
		this->fresh();
		return true;
	}
	return false;
}

bool BTableWidget::setItem(int row, int column, const BString& text)
{
	if (!member.items.check(row, column))
		return false;
	BTableItemHolder item = this->item(row, column);
	if (!item)
	{
		item = new BTableItem();
		setItem(row, column, item);
	}
	item->setText(text);
	member.dirty = true;
	this->fresh();
	return true;
}
bool BTableWidget::setItem(int row, int column, BWidget* widget)
{
	if (!widget)
		return false;
	if (!member.items.check(row, column))
		return false;
	BTableItemHolder item = this->item(row, column);
	if (!item)
	{
		item = new BTableItem();
		setItem(row, column, item);
	}
	item->setWidget(widget);
	member.dirty = true;
	this->fresh();
	return true;
}
bool BTableWidget::setItem(int row, int column, BTableItem* item)
{
	if (!member.items.check(row, column))
		return false;
	if (member.items[row][column] == item)
		return true;
	BTableItem* oldItem = member.items[row][column];
	this->removeItem(oldItem);
	if (item)
	{
		item_member(item)->table = this;
		item_member(item)->row = row;
		item_member(item)->column = column;
		this->addChild(item_member(item)->widget);
	}
	member.items[row][column] = item;
	member.dirty = true;
	this->fresh();
	return true;
}
BTableItem* BTableWidget::item(int row, int column)
{
	return member.items(row, column);
}
const BTableItem* BTableWidget::item(int row, int column) const
{
	return member.items(row, column);
}

BTableItem* BTableWidget::item(const BValue& value)
{
	for (auto it = member.items.begin(); it.valid(); it++)
	{
		if (*it && item_member(*it)->value == value)
		{
			return *it;
		}
	}
	return 0;
}
const BTableItem* BTableWidget::item(const BValue& value) const
{
	for (auto it = member.items.begin(); it.valid(); it++)
	{
		if (*it && item_member(*it)->value == value)
		{
			return *it;
		}
	}
	return 0;
}

BTableItem* BTableWidget::item(int column, const BValue& value)
{
	for (int r = 0; r < member.items.row(); r++)
	{
		BTableItem* item = member.items[r][column];
		if (item && item_member(item)->value == value)
		{
			return item;
		}
	}
	return 0;
}
const BTableItem* BTableWidget::item(int column, const BValue& value) const
{
	for (int r = 0; r < member.items.row(); r++)
	{
		const BTableItem* item = member.items[r][column];
		if (item && item_member(item)->value == value)
		{
			return item;
		}
	}
	return 0;
}

BTableItem* BTableWidget::item(const BString& text)
{
	for (auto it = member.items.begin(); it.valid(); it++)
	{
		BTableItem* item = *it;
		if (item && item_member(item)->text == text)
		{
			return *it;
		}
	}
	return 0;
}
const BTableItem* BTableWidget::item(const BString& text) const
{
	for (auto it = member.items.begin(); it.valid(); it++)
	{
		const BTableItem* item = *it;
		if (item && item_member(item)->text == text)
		{
			return *it;
		}
	}
	return 0;
}

BTableItem* BTableWidget::item(int column, const BString& text)
{
	for (int r = 0; r < member.items.row(); r++)
	{
		BTableItem* item = member.items[r][column];
		if (item && item_member(item)->text == text)
		{
			return item;
		}
	}
	return 0;
}
const BTableItem* BTableWidget::item(int column, const BString& text) const
{
	for (int r = 0; r < member.items.row(); r++)
	{
		const BTableItem* item = member.items[r][column];
		if (item && item_member(item)->text == text)
		{
			return item;
		}
	}
	return 0;
}

bool BTableWidget::addItem(BTableItem* item)
{
	if (member.items.column() < 1)
		appendColumn(1);
	while (!member.items.contain((BTableItem*)0))
		appendRow(1);
	auto it = member.items.find((BTableItem*)0);
	if (it.valid())
	{
		*it = item;
		return true;
	}
	return false;
}
bool BTableWidget::removeItem(const BTableItem* item)
{
	if (!item)
		return false;

	if (item_member(item)->table != this)
		return false;

	member.selectedItems.remove(item);
	if (member.hoverItem == item)
		member.hoverItem = 0;
	if (member.shiftItem == item)
		member.shiftItem = member.selectedItems.first();
	if (item_member(item)->widget)
		this->removeChild(item_member(item)->widget);

	int column = item_member(item)->column;
	int row = item_member(item)->row;
	if (member.items.check(row, column))
	{
		item_member(item)->row = -1;
		item_member(item)->column = -1;

		item_member(item)->table = 0;
		member.items[row][column] = 0;
	}
	else
	{
		int a = 0;
	}
	member.dirty = true;
	this->fresh();
	return true;
}

BTableItem* BTableWidget::itemAt(int x, int y)
{
	return member.itemAtPoint(BPoint(x, y));
}
const BTableItem* BTableWidget::itemAt(int x, int y) const
{
	return member.itemAtPoint(BPoint(x, y));
}

BTableItem* BTableWidget::itemAt(const BPoint& pos)
{
	return member.itemAtPoint(pos);
}
const BTableItem* BTableWidget::itemAt(const BPoint& pos) const
{
	return member.itemAtPoint(pos);
}

BRect BTableWidget::cellRect(int row, int column) const
{
	if (!member.items.check(row, column))
		return BRect();
	const BRect& colRect = member.columnHeader.sections[column].rect;
	const BRect& rowRect = member.rowHeader.sections[row].rect;
	return BRect(colRect.x(), rowRect.y(), colRect.width(), rowRect.height());
}

void BTableWidget::scroll(BTableWidget* item, Align align)
{
	BRect crect = this->clientRect();
	BRect area = this->area();
	if (item)
	{
		BRect rect = item->rect();
		rect = crect.align(align, rect.size());
		area.setPos(rect.pos());
	}
	else
	{
		area = crect.align(align, area.size());
	}
	this->setArea(area);
}

bool BTableWidget::sort(int column)
{
	if (!member.columnHeader.sortable)
		return false;
	if (column < 0)
	{
		for (int i = 0; i < member.columnHeader.sections.size(); i++)
		{
			if (member.columnHeader.sections[i].sortMode)
			{
				column = i;
				break;
			}
		}
	}
	if (!member.columnHeader.sections.check(column))
		return false;
	return member.sortColumn(column);
}
void BTableWidget::clear()
{
	member.columnHeader.sections.clear();
	member.rowHeader.sections.clear();
	member.items.clear();
	member.dirty = true;
	this->fresh();
}
void BTableWidget::reset()
{
	member.items.reset();
	member.dirty = true;
	this->fresh();
}

void BTableWidget::setSortable(bool sortable)
{
	if (member.columnHeader.sortable != sortable)
	{
		member.columnHeader.sortable = sortable;
		for (int i = 0; i < member.columnHeader.sections.size(); i++)
		{
			member.columnHeader.sections[i].sortMode = 0;
		}
		this->fresh();
	}
}
bool BTableWidget::sortable() const
{
	return member.columnHeader.sortable;
}

void BTableWidget::setGridStyle(GridStyle gridStyle)
{
	if (member.gridStyle != gridStyle)
	{
		member.gridStyle = gridStyle;
		fresh();
	}
}
GridStyle BTableWidget::gridStyle() const
{
	return member.gridStyle;
}

bool BTableWidget::setRowHeight(int row, int height)
{
	if (member.rowHeader.sections.check(row))
	{
		HeaderSection& sec = member.rowHeader.sections[row];
		if (sec.policy == Policy_Fixed)
			return false;
		if (sec.size != height)
		{
			sec.size = height;
			sec.dirty = true;
			sec.policy = Policy_Fixed;
			member.rowHeader.dirty = true;
			member.dirty = true;
			this->fresh();
		}
		return true;
	}
	return false;
}
int BTableWidget::rowHeight(int row) const
{
	return member.rowHeader.sections[row].rect.height();
}

BRect BTableWidget::rowRect(int row) const
{
	BRect rect = member.rowHeader.sections[row].rect;
	rect.left() = member.columnHeader.sections.first().rect.left();
	rect.right() = member.columnHeader.sections.last().rect.right();
	return rect;
}
BRect BTableWidget::rowHeaderRect(int row) const
{
	return member.rowHeader.sections[row].rect;
}

bool BTableWidget::setColumnWidth(int column, int width)
{
	if (member.columnHeader.sections.check(column))
	{
		HeaderSection& sec = member.columnHeader.sections[column];
		if (sec.policy == Policy_Fixed)
			return false;
		if(sec.size != width)
		{
			sec.size = width;
			sec.dirty = true;
			sec.policy = Policy_Fixed;
			member.columnHeader.dirty = true;
			member.dirty = true;
			this->fresh();
		}
		return true;
	}
	return false;
}
int BTableWidget::columnWidth(int column) const
{
	return member.columnHeader.sections(column).rect.width();
}

BRect BTableWidget::columnHeaderRect(int column) const
{
	return member.columnHeader.sections(column).rect;
}
BRect BTableWidget::columnRect(int column) const
{
	BRect rect = member.columnHeader.sections(column).rect;
	rect.top() = member.rowHeader.sections.first().rect.top();
	rect.bottom() = member.rowHeader.sections.last().rect.bottom();
	return rect;
}

void BTableWidget::setSelectMultiple(bool selectMultiple)
{
	if (member.selectMultiple != selectMultiple)
	{
		member.selectMultiple = selectMultiple;
		member.selectedItems.clear();
		this->fresh();
	}
}
bool BTableWidget::selectMultiple() const
{
	return member.selectMultiple;
}

void BTableWidget::setSelectedItem(BTableItem* item, bool selected)
{
	if (!item)
		return;

	if (selected && !member.selectedItems.contain(item))
	{
		if (member.selectMultiple == false)
		{
			member.selectedItems.clear();
		}
		member.selectedItems.append(item);
		emit(Signal_ItemSelected, item);
		return;
	}
	if (!selected && member.selectedItems.remove(item))
	{
		emit(Signal_ItemUnSelected, item);
		return;
	}
}

int BTableWidget::selectedItemCount() const
{
	return member.selectedItems.size();
}
BTableItem* BTableWidget::selectedItem(int index)
{
	return member.selectedItems(index);
}
const BTableItem* BTableWidget::selectedItem(int index) const
{
	return member.selectedItems(index);
}

void BTableWidget::scrollArea()
{
	if (member.columnHeader.sections.size())
	{
		member.columnHeader.dirty = true;
	}
	if (member.rowHeader.sections.size())
	{
		member.rowHeader.dirty = true;
	}
	member.dirty = true;
	this->fresh();
}

void BTableWidget::adjustEvent(const BEvent& event)
{
	const BRect& topRect = this->rect(Part_Top);
	member.columnHeader.dirty = true;
	member.rowHeader.dirty = true;
	member.dirty = true;
	this->fresh();
}
void BTableWidget::styleEvent(const BEvent& changeEvent)
{
	const BFont* font = this->font();
	if (font)
	{
		this->verticalScrollBar()->setStep(font->height());
		member.columnHeader.dirty = true;
		member.rowHeader.dirty = true;
		member.dirty = true;
	}
}
void BTableWidget::freshEvent(const BEvent& event)
{
	BScrollArea::freshEvent(event);
	if (member.dirty)
	{
		member.adjustHeader();
		member.adjustItemRects();
		member.dirty = false;
	}
	BRect area = this->area();
	int col_length = member.columnHeader.sections.last().rect.right() - member.columnHeader.sections.first().rect.left();
	int row_length = member.rowHeader.sections.last().rect.bottom() - member.rowHeader.sections.first().rect.top();
	area.setSize(col_length, row_length);
	this->setArea(area);

}
void BTableWidget::paintEvent(const BEvent& event)
{
	BPainter painter(this);
	painter.drawBackground();
	painter.drawContent();

	painter.setClip(this->clientRect());

	if (member.gridStyle & Grid_Horizontal && member.rowHeader.sections.size() > 1)
	{
		if (painter.setColor(Color_Grid_Hor))
		{
			int x0 = member.columnHeader.sections.first().rect.left();
			int x1 = member.columnHeader.sections.last().rect.right();
			for (int r = 0; r < member.rowHeader.sections.size(); r++)
			{
				int y = member.rowHeader.sections[r].rect.bottom() + member.rowHeader.space / 2;
				painter.drawLine(x0, y, x1, y);
			}
		}
	}

	if (member.gridStyle & Grid_Vertical && member.columnHeader.sections.size() > 1)
	{
		if (painter.setColor(Color_Grid_Ver))
		{
			int y0 = member.rowHeader.sections.first().rect.top();
			int y1 = member.rowHeader.sections.last().rect.bottom();
			for (int c = 0; c < member.columnHeader.sections.size(); c++)
			{
				int x = member.columnHeader.sections[c].rect.right() + member.columnHeader.space / 2;
				painter.drawLine(x, y0, x, y1);
			}
		}
	}

	int row_first = member.rowHeader.show_first;
	int row_count = member.rowHeader.show_count;
	int col_first = member.columnHeader.show_first;
	int col_count = member.columnHeader.show_count;
	for (int r = row_first; r < row_first + row_count; r++)
	{
		if (!member.rowHeader.sections[r].visible)
			continue;
		BTable<BTableItemHolder>& items = member.items;
		for (int c = col_first; c < col_first + col_count; c++)
		{
			BTableItem* item = items[r][c];
			if (!item)
				continue;
			BRect rect = item_member(item)->rect;
			bool selected = member.selectedItems.contain(item);
			if (item_member(item)->color.a() > 1)
			{
				painter.setColor(item_member(item)->color);
				painter.fillRect(item_member(item)->rect);
				if (selected)
					painter.setColor(Color_Item_Selected);
				else if (member.hoverItem == item)
					painter.setColor(Color_Item_Hovered);
				else
					painter.setColor(Color_Item);
				painter.drawRect(item_member(item)->rect);
			}
			else
			{
				if (selected)
				{
					painter.setColor(Color_Item_Selected);
					painter.fillRect(item_member(item)->rect);
				}
				else if (member.hoverItem == item)
				{
					painter.setColor(Color_Item_Hovered);
					painter.fillRect(item_member(item)->rect);
				}
			}
			if (item_member(item)->image)
			{
				painter.setColor(255, 255, 255);
				painter.drawImage(item_member(item)->imageRect, item->image());
			}
			if (item_member(item)->text.size())
			{
				painter.setColor(Color_Text);
				if (selected)
					painter.setColor(Color_Text_Checked);
				else if (member.hoverItem == item)
					painter.setColor(Color_Text_Hovered);
				painter.drawText(item_member(item)->textRect, item->text(), item->lineFeed());
			}
		}
	}
	painter.setClip(0, 0, this->width(), this->height());

	painter.drawPerch();

	painter.setClip(this->rect(Part_Top));
	member.columnHeader.paint(painter);
	painter.setClip(0, 0, this->width(), this->height());

	painter.setClip(this->rect(Part_Left));
	member.rowHeader.paint(painter);
	painter.setClip(0, 0, this->width(), this->height());

	painter.drawMargin();
	painter.drawBorder();
}

void BTableWidget::keyDownEvent(const BKeyEvent& keyEvent)
{
	Key key = keyEvent.key();
	if (key == Key_LShift || key == Key_RShift)
	{
		member.shift = true;
		member.shiftItem = member.selectedItems.first();
	}
	if (key == Key_LCtrl || key == Key_RCtrl)
	{
		member.ctrl = true;
	}
}
void BTableWidget::keyUpEvent(const BKeyEvent& keyEvent)
{
	Key key = keyEvent.key();
	if (key == Key_LShift || key == Key_RShift)
	{
		member.shift = false;
		member.shiftItem = 0;
	}
	if (key == Key_LCtrl || key == Key_RCtrl)
	{
		member.ctrl = false;
	}
}

void BTableWidget::mouseEnterEvent(const BMouseEvent& mouseEvent)
{

}
void BTableWidget::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (member.columnHeader.hoverIndex >= 0)
	{
		member.columnHeader.hoverIndex = -1;
		this->fresh();
	}
	if (member.rowHeader.hoverIndex >= 0)
	{
		member.rowHeader.hoverIndex = -1;
		this->fresh();
	}
	if (member.hoverItem)
	{
		member.hoverItem = 0;
		this->fresh();
	}
}

void BTableWidget::mousePressEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	const BRect& topRect = this->rect(Part_Top);
	if (topRect.contain(pos))
	{
		if (member.columnHeader.handle >= 0)
		{
			member.columnHeader.draging = true;
			member.columnHeader.dragingPoint = pos;
			this->fresh();
			return;
		}
		if (member.columnHeader.hoverIndex >= 0)
		{
			member.columnHeader.pressed = true;
			this->fresh();
			return;
		}
	}

	const BRect& leftRect = this->rect(Part_Left);
	if (leftRect.contain(pos))
	{
		if (member.rowHeader.handle >= 0)
		{
			member.rowHeader.draging = true;
			member.rowHeader.dragingPoint = pos;
			this->fresh();
			return;
		}
		if (member.rowHeader.hoverIndex >= 0)
		{
			member.rowHeader.pressed = true;
			this->fresh();
			return;
		}
	}
}
void BTableWidget::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (member.columnHeader.draging)
	{
		member.columnHeader.draging = false;
		this->fresh();
	}
	if (member.columnHeader.pressed)
	{
		member.columnHeader.pressed = false;
		this->fresh();
	}
	if (member.rowHeader.draging)
	{
		member.rowHeader.draging = false;
		this->fresh();
	}
	if (member.rowHeader.pressed)
	{
		member.rowHeader.pressed = false;
		this->fresh();
	}
}
void BTableWidget::mouseMoveEvent(const BMouseEvent& event)
{
	const BPoint& pos = event.pos();

	if (member.columnHeader.draging)
	{
		if (member.columnHeader.drag(pos))
		{
			member.dirty = true;
			this->fresh();
		}
		return;
	}

	if (member.rowHeader.draging)
	{
		if (member.rowHeader.drag(pos))
		{
			member.dirty = true;
			this->fresh();
		}
		return;
	}

	BTableItem* item = member.itemAtPoint(pos);
	if (member.hoverItem != item)
	{
		member.hoverItem = item;
		this->fresh();
	}

	{
		const BRect& topRect = this->rect(Part_Top);

		int handle = -1;
		if (topRect.contain(pos))
			handle = member.columnHeader.handleUnderPoint(pos);
		if (member.columnHeader.handle != handle)
		{
			member.columnHeader.handle = handle;
			this->fresh();
		}
		int hoverIndex = -1;
		if (handle < 0 && topRect.contain(pos))
			hoverIndex = member.columnHeader.sectionUnderPoint(pos);
		if (member.columnHeader.hoverIndex != hoverIndex)
		{
			member.columnHeader.hoverIndex = hoverIndex;
			this->fresh();
		}
	}

	{
		const BRect& leftRect = this->rect(Part_Left);

		int handle = -1;
		if (leftRect.contain(pos))
			handle = member.rowHeader.handleUnderPoint(pos);
		if (member.rowHeader.handle != handle)
		{
			member.rowHeader.handle = handle;
			this->fresh();
		}
		int hoverIndex = -1;
		if (handle < 0 && leftRect.contain(pos))
			hoverIndex = member.rowHeader.sectionUnderPoint(pos);
		if (member.rowHeader.hoverIndex != hoverIndex)
		{
			member.rowHeader.hoverIndex = hoverIndex;
			this->fresh();
		}
	}
}
void BTableWidget::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	BScrollArea::mouseWheelEvent(mouseEvent);
}

void BTableWidget::mouseClickEvent(const BMouseEvent& event)
{
	if (event.button() == Button_Left)
	{
		if (member.columnHeader.hoverIndex >= 0)
		{
			if (member.columnHeader.sortable)
			{
				HeaderSection& sec = member.columnHeader.sections[member.columnHeader.hoverIndex];
				if (sec.sortMode == 0)
					sec.sortMode = -1;
				else
					sec.sortMode = -sec.sortMode;
				for (int i = 0; i < member.columnHeader.sections.size(); i++)
				{
					HeaderSection& sec = member.columnHeader.sections[i];
					if (member.columnHeader.hoverIndex != i)
						sec.sortMode = 0;
				}
				member.sortColumn(member.columnHeader.hoverIndex);
				this->fresh();
			}
			return;
		}
		const BPoint& pos = event.pos();
		BTableItem* item = member.itemAtPoint(pos);
		if (item && item->editable() && member.selectedItems.size() == 1 && member.selectedItems.first() == item)
		{
			if (!member.itemEdit)
			{
				member.itemEdit = new ItemEdit();
				this->addChild(member.itemEdit);
			}
			member_BTableWidget* mem = &member;
			member.itemEdit->item = item;
			BRect rect = item_member(item)->rect;
			rect.left() = item_member(item)->imageRect.right();
			member.itemEdit->setRect(rect);
			member.itemEdit->popup();
			return;
		}
		if (member.selectMultiple)
		{
			if (item && member.shift)
			{
				if (member.shiftItem == 0)
				{
					member.shiftItem = item;
					member.selectedItems.append(item);
					emit(Signal_ItemSelected, item);
					this->fresh();
				}
				else
				{
					BArray<BTableItem*> items;
					int row_begin = bMin(item->row(), member.shiftItem->row());
					int row_end = bMax(item->row(), member.shiftItem->row());

					items.resize(row_end - row_begin);
					items.reset();

					for (int r = row_begin; r <= row_end; r++)
					{
						item = member.items[r][0];
						items.append(item);
					}

					for (int i = 0; i < member.selectedItems.size(); i++)
					{
						item = member.selectedItems[i];
						if (!items.contain(item))
						{
							i--;
							member.selectedItems.remove(item);
							emit(Signal_ItemUnSelected, item);
						}
					}
					for (int i = 0; i < items.size(); i++)
					{
						item = items[i];
						if (!member.selectedItems.contain(item))
						{
							member.selectedItems.append(item);
							emit(Signal_ItemSelected, item);
						}
					}
					this->fresh();
				}
			}
			else if (item && member.ctrl)
			{
				if (member.selectedItems.contain(item))
				{
					member.selectedItems.remove(item);
					emit(Signal_ItemUnSelected, item);
					this->fresh();
				}
				else
				{
					member.selectedItems.append(item);
					emit(Signal_ItemSelected, item);
					this->fresh();
				}
			}
			else
			{
				for (int i = 0; i < member.selectedItems.size(); i++)
				{
					BTableItem* old_item = member.selectedItems[i];
					if (old_item != item)
					{
						i--;
						member.selectedItems.remove(old_item);
						emit(Signal_ItemUnSelected, old_item);
					}
				}
				if (item && member.selectedItems.empty())
				{
					member.selectedItems.append(item);
					emit(Signal_ItemSelected, item);
				}
				this->fresh();
			}
		}
		if (member.selectMultiple == false)
		{
			if (member.selectedItems.size() == 1 && member.selectedItems.first() != item)
			{
				BTableItem* old_item = member.selectedItems.first();
				member.selectedItems.clear();
				//emit(Signal_ItemUnSelected, old_item);
				this->fresh();
			}
			if (item)
			{
				member.selectedItems.append(item);
				emit(Signal_ItemSelected, item);
				this->fresh();
			}
		}
		emit(Signal_ItemClicked, item);
	}
}
void BTableWidget::mouseDoubleClickEvent(const BMouseEvent& event)
{
	if (event.button() == Button_Left)
	{
		const BPoint& pos = event.pos();
		BTableItem* item = member.itemAtPoint(pos);
		emit(Signal_ItemDoubleClicked, item);
	}
}
